<!DOCTYPE html>
<html>
<head><meta name="generator" content="Hexo 3.8.0">
    

    

    



    <meta charset="utf-8">
    
    
    
    
    <title>vue-项目记录 | lafen | lafen&#39;s personal blog</title>
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    
    <meta name="theme-color" content="#3F51B5">
    
    
    <meta name="keywords" content="vue,record">
    <meta name="description" content="记录1. 生产环境依赖包选项1234567891011&quot;dependencies&quot;: &amp;#123;    &quot;axios&quot;: &quot;0.18.1&quot;,    &quot;element-ui&quot;: &quot;^2.12.0&quot;,    &quot;js-cookie&quot;: &quot;2.2.0&quot;,    &quot;normalize.css&quot;: &quot;7.0.0&quot;,    &quot;nprogress&quot;: &quot;0.2.0&quot;,    &quot;path-to-regexp&quot;:">
<meta name="keywords" content="vue,record">
<meta property="og:type" content="article">
<meta property="og:title" content="vue-项目记录">
<meta property="og:url" content="https://lafen.gitee.io/2019/11/20/vue-项目记录/vue-项目记录/index.html">
<meta property="og:site_name" content="lafen">
<meta property="og:description" content="记录1. 生产环境依赖包选项1234567891011&quot;dependencies&quot;: &amp;#123;    &quot;axios&quot;: &quot;0.18.1&quot;,    &quot;element-ui&quot;: &quot;^2.12.0&quot;,    &quot;js-cookie&quot;: &quot;2.2.0&quot;,    &quot;normalize.css&quot;: &quot;7.0.0&quot;,    &quot;nprogress&quot;: &quot;0.2.0&quot;,    &quot;path-to-regexp&quot;:">
<meta property="og:locale" content="zh-CN">
<meta property="og:updated_time" content="2020-01-10T09:10:27.922Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="vue-项目记录">
<meta name="twitter:description" content="记录1. 生产环境依赖包选项1234567891011&quot;dependencies&quot;: &amp;#123;    &quot;axios&quot;: &quot;0.18.1&quot;,    &quot;element-ui&quot;: &quot;^2.12.0&quot;,    &quot;js-cookie&quot;: &quot;2.2.0&quot;,    &quot;normalize.css&quot;: &quot;7.0.0&quot;,    &quot;nprogress&quot;: &quot;0.2.0&quot;,    &quot;path-to-regexp&quot;:">
    
        <link rel="alternate" type="application/atom+xml" title="lafen" href="/atom.xml">
    
    <link rel="shortcut icon" href="/img/favicon.ico">
    <link rel="stylesheet" href="//unpkg.com/hexo-theme-material-indigo@latest/css/style.css">
    <script>window.lazyScripts=[]</script>

    <!-- custom head -->
    

</head>

<body>
    <div id="loading" class="active"></div>

    <aside id="menu" class="hide">
  <div class="inner flex-row-vertical">
    <a href="javascript:;" class="header-icon waves-effect waves-circle waves-light" id="menu-off">
        <i class="icon icon-lg icon-close"></i>
    </a>
    <div class="brand-wrap" style="background-image:url(/img/brand.jpg)">
      <div class="brand">
        <a href="/" class="avatar waves-effect waves-circle waves-light">
          <img src="/img/avatar.jpg">
        </a>
        <hgroup class="introduce">
          <h5 class="nickname">lafen</h5>
          <a href="mailto:1031822863@qq.com" title="1031822863@qq.com" class="mail">1031822863@qq.com</a>
        </hgroup>
      </div>
    </div>
    <div class="scroll-wrap flex-col">
      <ul class="nav">
        
            <li class="waves-block waves-effect">
              <a href="/">
                <i class="icon icon-lg icon-home"></i>
                home
              </a>
            </li>
        
            <li class="waves-block waves-effect">
              <a href="/archives">
                <i class="icon icon-lg icon-archives"></i>
                Archives
              </a>
            </li>
        
            <li class="waves-block waves-effect">
              <a href="/tags">
                <i class="icon icon-lg icon-tags"></i>
                Tags
              </a>
            </li>
        
            <li class="waves-block waves-effect">
              <a href="/categories">
                <i class="icon icon-lg icon-th-list"></i>
                Categories
              </a>
            </li>
        
            <li class="waves-block waves-effect">
              <a href="https://github.com/zhongxiaotian" target="_blank">
                <i class="icon icon-lg icon-github"></i>
                Github
              </a>
            </li>
        
            <li class="waves-block waves-effect">
              <a href="http://www.weibo.com/" target="_blank">
                <i class="icon icon-lg icon-weibo"></i>
                Weibo
              </a>
            </li>
        
            <li class="waves-block waves-effect">
              <a href="https://gitee.com/lafen" target="_blank">
                <i class="icon icon-lg icon-link"></i>
                Gitee
              </a>
            </li>
        
      </ul>
    </div>
  </div>
</aside>

    <main id="main">
        <header class="top-header" id="header">
    <div class="flex-row">
        <a href="javascript:;" class="header-icon waves-effect waves-circle waves-light on" id="menu-toggle">
          <i class="icon icon-lg icon-navicon"></i>
        </a>
        <div class="flex-col header-title ellipsis">vue-项目记录</div>
        
        <div class="search-wrap" id="search-wrap">
            <a href="javascript:;" class="header-icon waves-effect waves-circle waves-light" id="back">
                <i class="icon icon-lg icon-chevron-left"></i>
            </a>
            <input type="text" id="key" class="search-input" autocomplete="off" placeholder="输入感兴趣的关键字">
            <a href="javascript:;" class="header-icon waves-effect waves-circle waves-light" id="search">
                <i class="icon icon-lg icon-search"></i>
            </a>
        </div>
        
        
        <a href="javascript:;" class="header-icon waves-effect waves-circle waves-light" id="menuShare">
            <i class="icon icon-lg icon-share-alt"></i>
        </a>
        
    </div>
</header>
<header class="content-header post-header">

    <div class="container fade-scale">
        <h1 class="title">vue-项目记录</h1>
        <h5 class="subtitle">
            
                <time datetime="2019-11-20T09:56:26.000Z" itemprop="datePublished" class="page-time">
  2019-11-20
</time>


	<ul class="article-category-list"><li class="article-category-list-item"><a class="article-category-list-link" href="/categories/vue/">vue</a><ul class="article-category-list-child"><li class="article-category-list-item"><a class="article-category-list-link" href="/categories/vue/record/">record</a></li></ul></li></ul>

            
        </h5>
    </div>

    


</header>


<div class="container body-wrap">
    
    <aside class="post-widget">
        <nav class="post-toc-wrap post-toc-shrink" id="post-toc">
            <h4>TOC</h4>
            <ol class="post-toc"><li class="post-toc-item post-toc-level-1"><a class="post-toc-link" href="#记录"><span class="post-toc-number">1.</span> <span class="post-toc-text">记录</span></a><ol class="post-toc-child"><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#1-生产环境依赖包选项"><span class="post-toc-number">1.0.0.1.</span> <span class="post-toc-text">1. 生产环境依赖包选项</span></a></li><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#2-将element-ui由2-7-2换成2-12-0最新版"><span class="post-toc-number">1.0.0.2.</span> <span class="post-toc-text">2. 将element-ui由2.7.2换成2.12.0最新版</span></a></li><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#3-vue中使用normalize-css初始化全局样式"><span class="post-toc-number">1.0.0.3.</span> <span class="post-toc-text">3. vue中使用normalize.css初始化全局样式</span></a></li><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#4-使用-js-cookie保存登录的token"><span class="post-toc-number">1.0.0.4.</span> <span class="post-toc-text">4. 使用 js-cookie保存登录的token</span></a></li><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#5-使用nprogress进度条"><span class="post-toc-number">1.0.0.5.</span> <span class="post-toc-text">5. 使用nprogress进度条</span></a></li><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#6-path-to-regexp：-url的正则表达式"><span class="post-toc-number">1.0.0.6.</span> <span class="post-toc-text">6. path-to-regexp： url的正则表达式</span></a></li><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#7-vue-router-路由权限中的问题"><span class="post-toc-number">1.0.0.7.</span> <span class="post-toc-text">7. vue-router 路由权限中的问题</span></a></li><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#8-路由权限与权限指令"><span class="post-toc-number">1.0.0.8.</span> <span class="post-toc-text">8. 路由权限与权限指令</span></a><ol class="post-toc-child"><li class="post-toc-item post-toc-level-5"><a class="post-toc-link" href="#路由权限"><span class="post-toc-number">1.0.0.8.1.</span> <span class="post-toc-text">路由权限</span></a></li><li class="post-toc-item post-toc-level-5"><a class="post-toc-link" href="#指令权限"><span class="post-toc-number">1.0.0.8.2.</span> <span class="post-toc-text">指令权限</span></a></li></ol></li><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#9-使用vue-count-to"><span class="post-toc-number">1.0.0.9.</span> <span class="post-toc-text">9. 使用vue-count-to</span></a></li><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#目录结构"><span class="post-toc-number">1.0.0.10.</span> <span class="post-toc-text">目录结构</span></a></li></ol></li></ol>
        </nav>
    </aside>


<article id="post-vue-项目记录/vue-项目记录" class="post-article article-type-post fade" itemprop="blogPost">

    <div class="post-card">
        <h1 class="post-card-title">vue-项目记录</h1>
        <div class="post-meta">
            <time class="post-time" title="2019-11-20 17:56:26" datetime="2019-11-20T09:56:26.000Z" itemprop="datePublished">2019-11-20</time>

            
	<ul class="article-category-list"><li class="article-category-list-item"><a class="article-category-list-link" href="/categories/vue/">vue</a><ul class="article-category-list-child"><li class="article-category-list-item"><a class="article-category-list-link" href="/categories/vue/record/">record</a></li></ul></li></ul>



            
<span id="busuanzi_container_page_pv" title="文章总阅读量" style="display:none">
    <i class="icon icon-eye icon-pr"></i><span id="busuanzi_value_page_pv"></span>
</span>


        </div>
        <div class="post-content" id="post-content" itemprop="postContent">
            <h1 id="记录"><a href="#记录" class="headerlink" title="记录"></a>记录</h1><h4 id="1-生产环境依赖包选项"><a href="#1-生产环境依赖包选项" class="headerlink" title="1. 生产环境依赖包选项"></a>1. 生产环境依赖包选项</h4><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">"dependencies": &#123;</span><br><span class="line">    "axios": "0.18.1",</span><br><span class="line">    "element-ui": "^2.12.0",</span><br><span class="line">    "js-cookie": "2.2.0",</span><br><span class="line">    "normalize.css": "7.0.0",</span><br><span class="line">    "nprogress": "0.2.0",</span><br><span class="line">    "path-to-regexp": "2.4.0",</span><br><span class="line">    "vue": "2.6.10",</span><br><span class="line">    "vue-router": "3.0.6",</span><br><span class="line">    "vuex": "3.1.0"</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h4 id="2-将element-ui由2-7-2换成2-12-0最新版"><a href="#2-将element-ui由2-7-2换成2-12-0最新版" class="headerlink" title="2. 将element-ui由2.7.2换成2.12.0最新版"></a>2. 将<code>element-ui</code>由<code>2.7.2</code>换成<code>2.12.0</code>最新版</h4><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span><span class="bash"> 重新安装一下依赖即可</span></span><br><span class="line">npm uninstall element-ui</span><br><span class="line">npm install element-ui</span><br></pre></td></tr></table></figure>
<h4 id="3-vue中使用normalize-css初始化全局样式"><a href="#3-vue中使用normalize-css初始化全局样式" class="headerlink" title="3. vue中使用normalize.css初始化全局样式"></a>3. <code>vue</code>中使用<code>normalize.css</code>初始化全局样式</h4><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span><span class="bash"> 安装依赖包</span></span><br><span class="line">npm install normalize.css</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span><span class="bash"> 项目 main.js 中引入即可</span></span><br><span class="line">import 'normalize.css/normalize.css'</span><br></pre></td></tr></table></figure>
<h4 id="4-使用-js-cookie保存登录的token"><a href="#4-使用-js-cookie保存登录的token" class="headerlink" title="4. 使用 js-cookie保存登录的token"></a>4. 使用 <code>js-cookie</code>保存登录的<code>token</code></h4><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"># 安装依赖包</span><br><span class="line">npm install js-cookie</span><br><span class="line"></span><br><span class="line"><span class="comment">// 在使用的地方中引入使用，一般集中封装到一个文件里面进行存取，例如 auth.js</span></span><br><span class="line"><span class="keyword">import</span> Cookies <span class="keyword">from</span> <span class="string">'js-cookie'</span></span><br><span class="line"><span class="keyword">const</span> TokenKey = <span class="string">'Token'</span></span><br><span class="line"><span class="comment">// 将方法导出给外部使用</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> getToken = <span class="function"><span class="params">()</span> =&gt;</span> Cookies.get(TokenKey)</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> setToken = <span class="function"><span class="params">token</span> =&gt;</span> Cookies.set(TokenKey, token)</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> removeToken = <span class="function"><span class="params">()</span> =&gt;</span> Cookies.remove(TokenKey)</span><br><span class="line"></span><br><span class="line"><span class="comment">// 则请求拦截中可使用</span></span><br><span class="line"><span class="keyword">import</span> &#123; getToken &#125; <span class="keyword">from</span> <span class="string">'@/utils/auth'</span></span><br><span class="line">axios.interceptors.request.use(<span class="function"><span class="params">config</span> =&gt;</span> &#123;</span><br><span class="line">        config.headers[<span class="string">'X-Token'</span>] = getToken()</span><br><span class="line">    	<span class="keyword">return</span> config</span><br><span class="line">    &#125;</span><br><span class="line">)</span><br></pre></td></tr></table></figure>
<h4 id="5-使用nprogress进度条"><a href="#5-使用nprogress进度条" class="headerlink" title="5. 使用nprogress进度条"></a>5. 使用<code>nprogress</code>进度条</h4><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"># 安装依赖包</span><br><span class="line">npm install nprogress</span><br><span class="line"></span><br><span class="line"><span class="comment">// 可以在请求时显示进度条，也可以在路由跳转时显示，例如路由跳转时</span></span><br><span class="line"><span class="keyword">import</span> router <span class="keyword">from</span> <span class="string">'./router'</span> <span class="comment">// 引入router</span></span><br><span class="line"><span class="keyword">import</span> NProgress <span class="keyword">from</span> <span class="string">'nprogress'</span></span><br><span class="line"><span class="keyword">import</span> <span class="string">'nprogress/nprogress.css'</span> <span class="comment">// style</span></span><br><span class="line">Nprogress.configure(&#123; <span class="attr">showSpinner</span>: <span class="literal">false</span> &#125;) <span class="comment">// config</span></span><br><span class="line"><span class="comment">// before</span></span><br><span class="line">router.beforeEach(<span class="keyword">async</span>(to, <span class="keyword">from</span>, next) =&gt; &#123;</span><br><span class="line">	NProgress.start() <span class="comment">// 开始跑进度条</span></span><br><span class="line">	<span class="comment">// ...一些操作</span></span><br><span class="line">	next() <span class="comment">// 释放钩子继续往下</span></span><br><span class="line">&#125;)</span><br><span class="line"><span class="comment">// after</span></span><br><span class="line">router.afterEach(<span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line">	NProgress.done() <span class="comment">// 结束</span></span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>
<h4 id="6-path-to-regexp：-url的正则表达式"><a href="#6-path-to-regexp：-url的正则表达式" class="headerlink" title="6. path-to-regexp： url的正则表达式"></a>6. <code>path-to-regexp</code>： <code>url</code>的正则表达式</h4><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"># 安装依赖</span><br><span class="line">npm install path-to-regexp</span><br><span class="line"></span><br><span class="line"><span class="comment">// 引入</span></span><br><span class="line"><span class="keyword">import</span> pathToRegexp <span class="keyword">from</span> <span class="string">'path-to-regexp'</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 用于处理url中的地址与参数</span></span><br><span class="line"><span class="comment">// 1. pathToRegexp() 直接使用类似于js中的正则</span></span><br><span class="line"><span class="keyword">var</span> pathToRegexp = <span class="built_in">require</span>(<span class="string">'path-to-regexp'</span>)</span><br><span class="line"><span class="keyword">var</span> re = pathToRegexp(<span class="string">'/foo/:bar'</span>)</span><br><span class="line"><span class="built_in">console</span>.log(re)<span class="comment">// /^\/foo\/((?:[^\/]+?))(?:\/(?=$))?$/i</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 2. exec() 匹配url地址与规则是否相符</span></span><br><span class="line"><span class="keyword">var</span> match1 = re.exec(<span class="string">'/test/route'</span>);    <span class="comment">// 不相符返回 null</span></span><br><span class="line"><span class="keyword">var</span> match2 = re.exec(<span class="string">'/foo/route'</span>);     <span class="comment">// 相符返回数组</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 3. parse() 解析url字符串中的参数部分(:id)</span></span><br><span class="line"><span class="keyword">var</span> url = <span class="string">'/user/:id'</span> <span class="comment">// 或者 '/user?id=1'</span></span><br><span class="line"><span class="keyword">var</span> res = pathToRegexp.parse(url) <span class="comment">// 打印一个数组，包含url与参数id</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 4. compile() 快速填充 url 字符串的参数值</span></span><br><span class="line"><span class="keyword">var</span> url = <span class="string">'/user/:id/:name'</span></span><br><span class="line"><span class="keyword">var</span> data = &#123; <span class="attr">id</span>: <span class="number">1001</span>, <span class="attr">name</span>: <span class="string">'Andy'</span> &#125;</span><br><span class="line"><span class="keyword">var</span> res = pathToRegexp.compile(url)(data) <span class="comment">// '/user/1001/Andy'</span></span><br></pre></td></tr></table></figure>
<h4 id="7-vue-router-路由权限中的问题"><a href="#7-vue-router-路由权限中的问题" class="headerlink" title="7. vue-router 路由权限中的问题"></a>7. <code>vue-router</code> 路由权限中的问题</h4><p><strong><code>addRoutes</code>实现权限控制：</strong></p>
<p><code>vue-element-admin</code>中的权限分为<strong>静态路由</strong>与<strong>动态路由</strong>两部分，静态路由就是任何角色都可以访问的路由，动态路由则是根据角色权限，动态加载的路由，从而达到权限的目的。</p>
<p>其中是根据获取到的用户的角色，例如<code>admin、editor</code>，通过在路由配置的<code>meta</code>中判断当前路由可访问角色，决定是否加载该路由，然后通过<code>addRoutes</code>的方式加载动态路由。</p>
<p><strong>问题：</strong></p>
<p>但是问题在于，<code>addRoutes</code>帮我们注入新的路由，但是并没有帮你删除路由。</p>
<p><strong>情景：</strong></p>
<p>假设这么一种情况，在自己电脑上登录了<code>admin</code>账号，该账号拥有所有的路由权限，能访问所有的页面，此时路由中已经注入了所有的动态路由。</p>
<p>然后退出<code>admin</code>账号到登录页面，保持页面不刷新，此时<code>admin</code>的路由仍然存在，登录<code>editor</code>的账号，此时，路由又会去注入<code>editor</code>的路由，此时就包含了两种角色的动态路由，导致普通用户也可访问管理员的页面。</p>
<p><strong>解决：</strong></p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> Vue <span class="keyword">from</span> <span class="string">'vue'</span></span><br><span class="line"><span class="keyword">import</span> Router <span class="keyword">from</span> <span class="string">'vue-router'</span></span><br><span class="line">Vue.use(Router)</span><br><span class="line"><span class="comment">// ...constantRoutes</span></span><br><span class="line"><span class="keyword">const</span> createRouter = <span class="function"><span class="params">()</span> =&gt;</span> <span class="keyword">new</span> Router(&#123;</span><br><span class="line">  scrollBehavior: <span class="function"><span class="params">()</span> =&gt;</span> (&#123; <span class="attr">y</span>: <span class="number">0</span> &#125;),</span><br><span class="line">  routes: constantRoutes</span><br><span class="line">&#125;)</span><br><span class="line"><span class="keyword">const</span> router = createRouter()</span><br><span class="line"><span class="comment">// Detail see: https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465</span></span><br><span class="line"><span class="keyword">export</span> <span class="function"><span class="keyword">function</span> <span class="title">resetRouter</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">const</span> newRouter = createRouter()</span><br><span class="line">    router.matcher = newRouter.matcher</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> router</span><br></pre></td></tr></table></figure>
<p>通过新建一个<code>Router</code>，将新的<code>Router.matcher</code>赋值给当前应用管理的<code>Router</code>，从而达到更新路由配置的目的</p>
<p>调用时机可在用户<strong>退出登录</strong>时调用</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; resetRouter &#125; <span class="keyword">from</span> <span class="string">'@/router'</span></span><br><span class="line"><span class="comment">// 伪代码</span></span><br><span class="line">logout() &#123;</span><br><span class="line">    <span class="comment">// ...</span></span><br><span class="line">    resetRouter()</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h4 id="8-路由权限与权限指令"><a href="#8-路由权限与权限指令" class="headerlink" title="8. 路由权限与权限指令"></a>8. 路由权限与权限指令</h4><h5 id="路由权限"><a href="#路由权限" class="headerlink" title="路由权限"></a>路由权限</h5><p>后台系统免不了做权限控制，由于 <code>vue-element-admin</code> 中的权限控制为预设的，不能动态的<strong>添加角色</strong>，给角色<strong>分配路由</strong>这些功能，故无法采用预设角色的方式来做权限控制</p>
<p>但思路是相同的，前端区分<strong>静态路由</strong>与<strong>动态路由</strong>，静态路由包括<strong>登录、首页</strong>等所有账号都能访问的页面，动态路由则是根据账号角色来<strong>动态加载</strong>的部分，即都是要经过<strong>后台</strong>返回用户个人对应的<strong>id路由表</strong>，然后前端根据路由表，通过路由中的 <code>addRoutes</code> 方法将动态路由添加到路由中</p>
<p>那前端将怎样的一份<strong>id路由表</strong>保存到服务器呢？先看看路由</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> Vue <span class="keyword">from</span> <span class="string">'vue'</span></span><br><span class="line"><span class="keyword">import</span> Router <span class="keyword">from</span> <span class="string">'vue-router'</span></span><br><span class="line">Vue.use(Router)</span><br><span class="line"><span class="comment">// 一些不需要权限的静态路由(已删减)</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> constantRoutes = [</span><br><span class="line">  &#123;</span><br><span class="line">    path: <span class="string">'/login'</span>,</span><br><span class="line">  &#125;,</span><br><span class="line">  &#123;</span><br><span class="line">    path: <span class="string">'/'</span>,</span><br><span class="line">    children: [&#123;</span><br><span class="line">      path: <span class="string">'dashboard'</span>,</span><br><span class="line">    &#125;]</span><br><span class="line">  &#125;</span><br><span class="line">]</span><br><span class="line"><span class="comment">// 一些需要权限的动态路由部分</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> asyncRoutes = [</span><br><span class="line">  <span class="comment">// 轮播图管理</span></span><br><span class="line">  &#123;</span><br><span class="line">    path: <span class="string">'/banner'</span>,</span><br><span class="line">    <span class="comment">// ...</span></span><br><span class="line">    children: [&#123;</span><br><span class="line">      path: <span class="string">'banner-list'</span>,</span><br><span class="line">      <span class="comment">// ...</span></span><br><span class="line">    &#125;]</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="comment">// 商品管理</span></span><br><span class="line">  &#123;</span><br><span class="line">    path: <span class="string">'/goods'</span>,</span><br><span class="line">    children: [&#123;</span><br><span class="line">      path: <span class="string">'goods-list'</span>,</span><br><span class="line">    &#125;, &#123;</span><br><span class="line">      path: <span class="string">'goods-add'</span>,</span><br><span class="line">    &#125;, &#123;</span><br><span class="line">      path: <span class="string">'goods-cate'</span>,</span><br><span class="line">    &#125;]</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="comment">// 账号管理</span></span><br><span class="line">  &#123;</span><br><span class="line">    path: <span class="string">'/account'</span>,</span><br><span class="line">    children: [&#123;</span><br><span class="line">      path: <span class="string">'account-route-list'</span>,</span><br><span class="line">    &#125;, &#123;</span><br><span class="line">      path: <span class="string">'account-hospital-list'</span>,</span><br><span class="line">    &#125;, &#123;</span><br><span class="line">      path: <span class="string">'account-list'</span>,</span><br><span class="line">    &#125;]</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="comment">// 订单管理</span></span><br><span class="line">  &#123;</span><br><span class="line">    path: <span class="string">'/order'</span>,</span><br><span class="line">    children: [&#123;</span><br><span class="line">      path: <span class="string">'order-online-list'</span>,</span><br><span class="line">    &#125;, &#123;</span><br><span class="line">      path: <span class="string">'order-offline-list'</span>,</span><br><span class="line">    &#125;]</span><br><span class="line">  &#125;</span><br><span class="line">]</span><br><span class="line"><span class="keyword">const</span> createRouter = <span class="function"><span class="params">()</span> =&gt;</span> <span class="keyword">new</span> Router(&#123;</span><br><span class="line">  scrollBehavior: <span class="function"><span class="params">()</span> =&gt;</span> (&#123; <span class="attr">y</span>: <span class="number">0</span> &#125;),</span><br><span class="line">  routes: constantRoutes <span class="comment">// 初始只挂载静态路由</span></span><br><span class="line">&#125;)</span><br><span class="line"><span class="keyword">const</span> router = createRouter()</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="function"><span class="keyword">function</span> <span class="title">resetRouter</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">const</span> newRouter = createRouter()</span><br><span class="line">  router.matcher = newRouter.matcher <span class="comment">// reset router</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> router</span><br></pre></td></tr></table></figure>
<p>代码做了删减，但主要看 <strong><code>createRouter</code></strong> 函数这里，这里 <code>createRouter</code> 函数执行时，只传入了 <code>constantRoutes</code> 静态路由，并没有传入 <code>asyncRoutes</code> 动态路由</p>
<p>因为动态路由部分需要从服务器请求回来<strong>路由表id</strong>之后，跟前端动态路由<strong>比对</strong>，<strong>筛选</strong>出来可以加载的路由，才会去动态的加载这部分路由</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 后端返回的路由表id</span></span><br><span class="line">res = [<span class="number">0</span>, <span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">6</span>, <span class="number">7</span>, <span class="number">12</span>, <span class="number">13</span>]</span><br></pre></td></tr></table></figure>
<p>没错，后端只返回了一个数组，需要我们那这个数组去跟本地的一份简易<strong>路由表</strong>做比对筛选</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 本地保存的一份简易路由表</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> [</span><br><span class="line">  &#123; <span class="attr">id</span>: <span class="number">0</span>, <span class="attr">name</span>: <span class="string">'轮播图'</span>, <span class="attr">path</span>: <span class="string">'banner-list'</span>, <span class="attr">rootPath</span>: <span class="string">'/banner'</span> &#125;,</span><br><span class="line"></span><br><span class="line">  &#123; <span class="attr">id</span>: <span class="number">1</span>, <span class="attr">name</span>: <span class="string">'角色管理'</span>, <span class="attr">path</span>: <span class="string">'account-route-list'</span>, <span class="attr">rootPath</span>: <span class="string">'/account'</span> &#125;,</span><br><span class="line">  &#123; <span class="attr">id</span>: <span class="number">2</span>, <span class="attr">name</span>: <span class="string">'医院管理'</span>, <span class="attr">path</span>: <span class="string">'account-hospital-list'</span>, <span class="attr">rootPath</span>: <span class="string">'/account'</span> &#125;,</span><br><span class="line">  &#123; <span class="attr">id</span>: <span class="number">3</span>, <span class="attr">name</span>: <span class="string">'账号管理'</span>, <span class="attr">path</span>: <span class="string">'account-list'</span>, <span class="attr">rootPath</span>: <span class="string">'/account'</span> &#125;,</span><br><span class="line"></span><br><span class="line">  &#123; <span class="attr">id</span>: <span class="number">6</span>, <span class="attr">name</span>: <span class="string">'商品分类'</span>, <span class="attr">path</span>: <span class="string">'product-category-list'</span>, <span class="attr">rootPath</span>: <span class="string">'/product'</span> &#125;,</span><br><span class="line">  &#123; <span class="attr">id</span>: <span class="number">7</span>, <span class="attr">name</span>: <span class="string">'商品列表'</span>, <span class="attr">path</span>: <span class="string">'product-list'</span>, <span class="attr">rootPath</span>: <span class="string">'/product'</span> &#125;,</span><br><span class="line"></span><br><span class="line">  &#123; <span class="attr">id</span>: <span class="number">12</span>, <span class="attr">name</span>: <span class="string">'线上订单'</span>, <span class="attr">path</span>: <span class="string">'order-online-list'</span>, <span class="attr">rootPath</span>: <span class="string">'/order'</span> &#125;,</span><br><span class="line">  &#123; <span class="attr">id</span>: <span class="number">13</span>, <span class="attr">name</span>: <span class="string">'线下订单'</span>, <span class="attr">path</span>: <span class="string">'order-offline-list'</span>, <span class="attr">rootPath</span>: <span class="string">'/order'</span> &#125;</span><br><span class="line">]</span><br></pre></td></tr></table></figure>
<p>这是一份简易的路由表，做了部分删减，那是如何做筛选的呢？此处的思路跟 <code>vue-element-admin</code> 中的相同，在 <code>router.beforeEach</code> 中判断前端是否已挂载了动态路由，已加载的话则直接跳转页面，否则，就先去请求<strong>路由表id</strong>回来，在前端比对之后，筛选出可以加载的路由渲染，再进行页面的跳转</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line">router.beforeEach(<span class="keyword">async</span>(to, <span class="keyword">from</span>, next) =&gt; &#123;</span><br><span class="line">  <span class="keyword">const</span> hasToken = getToken()</span><br><span class="line"></span><br><span class="line">  <span class="keyword">if</span> (hasToken) &#123;</span><br><span class="line">    <span class="keyword">if</span> (to.path === <span class="string">'/login'</span>) &#123;</span><br><span class="line">      next(&#123; <span class="attr">path</span>: <span class="string">'/'</span> &#125;)</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">	  <span class="comment">// 是否有权限路由</span></span><br><span class="line">      <span class="keyword">const</span> hasRoutes = store.getters.permission_routes &amp;&amp; store.getters.permission_routes.length &gt; <span class="number">0</span></span><br><span class="line">      <span class="keyword">if</span> (hasRoutes) &#123;</span><br><span class="line">        <span class="comment">// 已加载路由了，则直接进入</span></span><br><span class="line">        next()</span><br><span class="line">      &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="comment">// 没有则先去请求服务器</span></span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">          <span class="comment">// 请求服务器，获取路由表id</span></span><br><span class="line">          <span class="keyword">let</span> pages = <span class="keyword">await</span> store.dispatch(<span class="string">'permission/getPageIds'</span>)</span><br><span class="line">          <span class="comment">// 根据路由表id去比对路由表</span></span><br><span class="line">          <span class="keyword">const</span> accessRoutes = <span class="keyword">await</span> store.dispatch(<span class="string">'permission/generateRoutes'</span>, pages)</span><br><span class="line"></span><br><span class="line">          <span class="comment">// 动态挂载路由</span></span><br><span class="line">          router.addRoutes(accessRoutes)</span><br><span class="line">          </span><br><span class="line">          next(&#123; ...to, <span class="attr">replace</span>: <span class="literal">true</span> &#125;)</span><br><span class="line">        &#125; <span class="keyword">catch</span> (error) &#123;</span><br><span class="line">          <span class="comment">// 失败重定向回登录页面</span></span><br><span class="line">          <span class="keyword">await</span> store.dispatch(<span class="string">'user/resetToken'</span>)</span><br><span class="line">          Message.error(error || <span class="string">'Has Error'</span>)</span><br><span class="line">          next(<span class="string">`/login?redirect=<span class="subst">$&#123;to.path&#125;</span>`</span>)</span><br><span class="line">        &#125;</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    <span class="comment">/* has no token*/</span></span><br><span class="line">    next(<span class="string">`/login?redirect=<span class="subst">$&#123;to.path&#125;</span>`</span>)</span><br><span class="line">  &#125;</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>
<p>那如何比对，从动态路由中取出需要加载的路由呢？其实是根据 <code>path</code> 来匹配的，看 <code>generateRoutes</code> 方法可知</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> actions = &#123;</span><br><span class="line">  generateRoutes(&#123; commit &#125;, pages) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function"><span class="params">resolve</span> =&gt;</span> &#123;</span><br><span class="line">      <span class="keyword">let</span> accessedRoutes = [] <span class="comment">// 挂载的路由</span></span><br><span class="line">      <span class="comment">// pages(id) -&gt; path</span></span><br><span class="line">      <span class="keyword">const</span> simpleRoutes = [] <span class="comment">// id相应的简单路由表</span></span><br><span class="line">      pages.forEach(<span class="function"><span class="params">id</span> =&gt;</span> &#123;</span><br><span class="line">        simpleRoutes.push(routeMap.find(<span class="function"><span class="params">v</span> =&gt;</span> v.id === id))</span><br><span class="line">      &#125;)</span><br><span class="line">      <span class="keyword">const</span> rootArr = simpleRoutes.map(<span class="function"><span class="params">v</span> =&gt;</span> v.rootPath) <span class="comment">// 取出所有根路由 path</span></span><br><span class="line">      <span class="keyword">const</span> childPath = simpleRoutes.map(<span class="function"><span class="params">v</span> =&gt;</span> v.path) <span class="comment">// 取出所有子路由 path</span></span><br><span class="line">      <span class="keyword">const</span> rootPath = <span class="built_in">Array</span>.from(<span class="keyword">new</span> <span class="built_in">Set</span>(rootArr)) <span class="comment">// 简单数组去重</span></span><br><span class="line">      <span class="keyword">const</span> routesTmp = asyncRoutes.filter(<span class="function"><span class="params">v</span> =&gt;</span> rootPath.some(<span class="function"><span class="params">i</span> =&gt;</span> i === v.path)) <span class="comment">// 从所有路由中取出根路由</span></span><br><span class="line">      routesTmp.forEach(<span class="function"><span class="params">route</span> =&gt;</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (!route.hasOwnProperty(<span class="string">'children'</span>) || route.children.length === <span class="number">1</span>) &#123;</span><br><span class="line">          accessedRoutes.push(route) <span class="comment">// 只有一个子路由，直接 push</span></span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">          <span class="keyword">const</span> routeCopy = <span class="built_in">Object</span>.assign(&#123;&#125;, route) <span class="comment">// 否则过滤子路由</span></span><br><span class="line">          routeCopy.children = routeCopy.children.filter(<span class="function"><span class="params">v</span> =&gt;</span> childPath.some(<span class="function"><span class="params">i</span> =&gt;</span> i === v.path))</span><br><span class="line">          accessedRoutes.push(routeCopy)</span><br><span class="line">        &#125;</span><br><span class="line">      &#125;)</span><br><span class="line">      accessedRoutes = accessedRoutes.concat(staticRoutes) <span class="comment">// 404</span></span><br><span class="line">      commit(<span class="string">'SET_ROUTES'</span>, accessedRoutes)</span><br><span class="line">      resolve(accessedRoutes)</span><br><span class="line">    &#125;)</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>既然是根据路由的 <code>path</code> 来做比对的，那服务器直接返回 <code>path</code> 给前端不就好了吗？</p>
<p>刚开始我也是这么做的，但是后端说他也要知道用户对应可以哪个路由，故做成了一份 <code>id</code> 对应路由的这样一份路由表，麻烦就是每新增一个路由，都得在路由表中添加一条，着实蛋疼。而且，路由层级只有两层…</p>
<p>暂且先这么干吧…</p>
<h5 id="指令权限"><a href="#指令权限" class="headerlink" title="指令权限"></a>指令权限</h5><p>以上也只能做页面级别的控制加载与否，对于页面上的按钮级别的颗粒度就不行了，但是可以利用角色来进行判断。</p>
<p>我们在登录系统的时候，会请求回来路由表之外，还会带回来账号的角色，假设系统中存在三种角色 <code>admin</code>、<code>merchant</code>、<code>clerk</code>，其中管理员账号登录之后返回角色 <code>admin</code>，将角色保存在 <code>vuex</code> 中，就可以根据角色来控制是否显示需要指定权限的页面元素，于是</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">	&lt;span v-if=&quot;isAdmin&quot;&gt;&#123;&#123; shop.name &#125;&#125;&lt;/span&gt;</span><br><span class="line">&lt;/template&gt;</span><br><span class="line">&lt;script&gt;</span><br><span class="line">import &#123; mapGetters &#125; from &apos;vuex&apos;</span><br><span class="line">export default &#123;</span><br><span class="line">  computed: &#123;</span><br><span class="line">    ...mapGetters([</span><br><span class="line">      &apos;roles&apos;,</span><br><span class="line">      &apos;isAdmin&apos;,</span><br><span class="line">      &apos;isMerchant&apos;,</span><br><span class="line">      &apos;isClerk&apos;</span><br><span class="line">    ])</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line">&lt;/script&gt;</span><br></pre></td></tr></table></figure>
<p>其中 <code>isAdmin</code>、<code>isMerchant</code>、<code>isClerk</code> 在 <code>getters</code> 中如下定义</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">isAdmin: <span class="function"><span class="params">state</span> =&gt;</span> state.user.roles.includes(<span class="string">'admin'</span>),</span><br><span class="line">isMerchant: <span class="function"><span class="params">state</span> =&gt;</span> state.user.roles.includes(<span class="string">'merchant'</span>),</span><br><span class="line">isClerk: <span class="function"><span class="params">state</span> =&gt;</span> state.user.roles.includes(<span class="string">'clerk'</span>),</span><br></pre></td></tr></table></figure>
<p>采用 <code>v-if</code> 来判断角色，达到控制显示隐藏的目的，实在繁琐，而更优雅的方法是，通过指令来实现权限控制</p>
<p>在 <code>src/directive/permission/permission.js</code> 中定义如下指令，引入 <code>store</code> ，判断其中的 <code>roles</code> 是否包含传入的角色，不包含则通过 <code>el.parentNode.removeChild(el)</code> 来删除掉该元素</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> store <span class="keyword">from</span> <span class="string">'@/store'</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">  inserted(el, binding, vnode) &#123;</span><br><span class="line">    <span class="keyword">const</span> &#123; value &#125; = binding</span><br><span class="line">    <span class="keyword">const</span> roles = store.getters &amp;&amp; store.getters.roles</span><br><span class="line">    <span class="keyword">if</span> (value &amp;&amp; <span class="built_in">Array</span>.isArray(value) &amp;&amp; value.length &gt; <span class="number">0</span>) &#123;</span><br><span class="line">      <span class="keyword">const</span> permissionRoles = value</span><br><span class="line">      <span class="keyword">const</span> hasPermission = roles.some(<span class="function"><span class="params">role</span> =&gt;</span> permissionRoles.includes(role))</span><br><span class="line">      <span class="keyword">if</span> (!hasPermission) &#123;</span><br><span class="line">        el.parentNode &amp;&amp; el.parentNode.removeChild(el)</span><br><span class="line">      &#125;</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      <span class="keyword">throw</span> <span class="keyword">new</span> <span class="built_in">Error</span>(<span class="string">`need roles! Like v-permission="['admin','editor']"`</span>)</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>在 <code>src/directive/permission/index.js</code> 中将指令通过 <code>install</code> 注册到 <code>directive</code></p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> permission <span class="keyword">from</span> <span class="string">'./permission'</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> install = <span class="function"><span class="keyword">function</span>(<span class="params">Vue</span>) </span>&#123;</span><br><span class="line">  Vue.directive(<span class="string">'permission'</span>, permission)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> (<span class="built_in">window</span>.Vue) &#123;</span><br><span class="line">  <span class="built_in">window</span>[<span class="string">'permission'</span>] = permission</span><br><span class="line">  Vue.use(install); <span class="comment">// eslint-disable-line</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">permission.install = install</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> permission</span><br></pre></td></tr></table></figure>
<p>使用起来就很优雅了，先引入注册，然后使用 <code>v-permission</code> 即可轻松根据角色控制显隐</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">	&lt;span v-permission=&quot;[&apos;admin&apos;]&quot;&gt;&#123;&#123; shop.name &#125;&#125;&lt;/span&gt;</span><br><span class="line">&lt;/template&gt;</span><br><span class="line">&lt;script&gt;</span><br><span class="line">import permission from &apos;@/directive/permission/index&apos;</span><br><span class="line">export default &#123;</span><br><span class="line">  directive: &#123;</span><br><span class="line">	permission</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line">&lt;/script&gt;</span><br></pre></td></tr></table></figure>
<p>指令还有很多好玩的地方，其中指令的钩子函数就有好几个，可根据钩子函数来实现一些 <code>dom</code> 等操作，钩子函数如下</p>
<ul>
<li><code>bind</code></li>
<li><code>inserted</code></li>
<li><code>update</code></li>
<li><code>componentUpdated</code></li>
<li><code>unbind</code></li>
</ul>
<p>具体的钩子和参数可参考官网<a href="https://cn.vuejs.org/v2/guide/custom-directive.html" target="_blank" rel="noopener">自定义指令</a></p>
<p>比如，需要在页面加载时候就让输入框聚焦，可进行如下配置</p>
<p><code>src/directive/focus/focus.js</code> 中</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">  inserted(el, binding, vnode) &#123;</span><br><span class="line">    <span class="keyword">let</span> element = el</span><br><span class="line">    <span class="comment">// 由于element包装了一层div，导致无法自动聚焦，需要做一下修正</span></span><br><span class="line">    <span class="keyword">if</span> (element.tagName !== <span class="string">'INPUT'</span>) &#123;</span><br><span class="line">      element = el.querySelector(<span class="string">"input[type='text']"</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    element.focus()</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p><code>src/directive/focus/index.js</code> 中</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> focus <span class="keyword">from</span> <span class="string">'./focus'</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> install = <span class="function"><span class="keyword">function</span>(<span class="params">Vue</span>) </span>&#123;</span><br><span class="line">  Vue.directive(<span class="string">'focus'</span>, focus)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> (<span class="built_in">window</span>.Vue) &#123;</span><br><span class="line">  <span class="built_in">window</span>[<span class="string">'focus'</span>] = focus</span><br><span class="line">  Vue.use(install) <span class="comment">// eslint-disable-line</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">focus.install = install</span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> focus</span><br></pre></td></tr></table></figure>
<p>使用 <code>v-focus</code></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">	&lt;el-input</span><br><span class="line">        v-focus</span><br><span class="line">        v-model=&quot;search&quot;</span><br><span class="line">        placeholder=&quot;通过指令自动聚焦&quot; /&gt;</span><br><span class="line">&lt;/template&gt;</span><br><span class="line">&lt;script&gt;</span><br><span class="line">import focus from &apos;@/directive/focus/index&apos;</span><br><span class="line">export default &#123;</span><br><span class="line">  directives: &#123;</span><br><span class="line">    focus</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line">&lt;/script&gt;</span><br></pre></td></tr></table></figure>
<h4 id="9-使用vue-count-to"><a href="#9-使用vue-count-to" class="headerlink" title="9. 使用vue-count-to"></a>9. 使用<code>vue-count-to</code></h4><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"># 安装依赖</span><br><span class="line">npm install vue-count-to</span><br><span class="line"></span><br><span class="line"><span class="comment">// 引入注册</span></span><br><span class="line"><span class="keyword">import</span> CountTo <span class="keyword">from</span> <span class="string">'vue-count-to'</span></span><br><span class="line">components: &#123;</span><br><span class="line">    CountTo</span><br><span class="line">&#125;,</span><br><span class="line"><span class="comment">// 使用即可，页面上数字会从 0 开始逐渐递增至 13600，时间为 3600ms</span></span><br><span class="line">&lt;count-to :start-val=<span class="string">"0"</span> :end-val=<span class="string">"13600"</span> :duration=<span class="string">"3600"</span> /&gt;</span><br></pre></td></tr></table></figure>
<h4 id="目录结构"><a href="#目录结构" class="headerlink" title="目录结构"></a>目录结构</h4><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line">├── build                      # 构建相关</span><br><span class="line">├── mock                       # 项目mock 模拟数据</span><br><span class="line">├── plop-templates             # 基本模板</span><br><span class="line">├── public                     # 静态资源</span><br><span class="line">│   │── favicon.ico            # favicon图标</span><br><span class="line">│   └── index.html             # html模板</span><br><span class="line">├── src                        # 源代码</span><br><span class="line">│   ├── api                    # 所有请求</span><br><span class="line">│   ├── assets                 # 主题 字体等静态资源</span><br><span class="line">│   ├── components             # 全局公用组件</span><br><span class="line">│   ├── directive              # 全局指令</span><br><span class="line">│   ├── filters                # 全局 filter</span><br><span class="line">│   ├── icons                  # 项目所有 svg icons</span><br><span class="line">│   ├── lang                   # 国际化 language</span><br><span class="line">│   ├── layout                 # 全局 layout</span><br><span class="line">│   ├── router                 # 路由</span><br><span class="line">│   ├── store                  # 全局 store管理</span><br><span class="line">│   ├── styles                 # 全局样式</span><br><span class="line">│   ├── utils                  # 全局公用方法</span><br><span class="line">│   ├── vendor                 # 公用vendor</span><br><span class="line">│   ├── views                  # views 所有页面</span><br><span class="line">│   ├── App.vue                # 入口页面</span><br><span class="line">│   ├── main.js                # 入口文件 加载组件 初始化等</span><br><span class="line">│   └── permission.js          # 权限管理</span><br><span class="line">├── tests                      # 测试</span><br><span class="line">├── .env.xxx                   # 环境变量配置</span><br><span class="line">├── .eslintrc.js               # eslint 配置项</span><br><span class="line">├── .babelrc                   # babel-loader 配置</span><br><span class="line">├── .travis.yml                # 自动化CI配置</span><br><span class="line">├── vue.config.js              # vue-cli 配置</span><br><span class="line">├── postcss.config.js          # postcss 配置</span><br><span class="line">└── package.json               # package.json</span><br></pre></td></tr></table></figure>

        </div>

        <blockquote class="post-copyright">
    
    <div class="content">
        
<span class="post-time">
    最后更新时间：<time datetime="2020-01-10T09:10:27.922Z" itemprop="dateUpdated">2020-01-10 17:10:27</time>
</span><br>


        
        关于学习类文章网上已经有非常多，而此处文章都是我在学习过程中整理摘录的笔记，参考文章可以点击文末的参考链接进行查阅
        
    </div>
    
    <footer>
        <a href="https://lafen.gitee.io">
            <img src="/img/avatar.jpg" alt="lafen">
            lafen
        </a>
    </footer>
</blockquote>

        
<div class="page-reward">
    <a id="rewardBtn" href="javascript:;" class="page-reward-btn waves-effect waves-circle waves-light">赏</a>
</div>



        <div class="post-footer">
            
	<ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/record/">record</a></li><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/vue/">vue</a></li></ul>


            
<div class="page-share-wrap">
    

<div class="page-share" id="pageShare">
    <ul class="reset share-icons">
      <li>
        <a class="weibo share-sns" target="_blank" href="http://service.weibo.com/share/share.php?url=https://lafen.gitee.io/2019/11/20/vue-项目记录/vue-项目记录/&title=《vue-项目记录》 — lafen&pic=https://lafen.gitee.io/img/avatar.jpg" data-title="微博">
          <i class="icon icon-weibo"></i>
        </a>
      </li>
      <li>
        <a class="weixin share-sns wxFab" href="javascript:;" data-title="微信">
          <i class="icon icon-weixin"></i>
        </a>
      </li>
      <li>
        <a class="qq share-sns" target="_blank" href="http://connect.qq.com/widget/shareqq/index.html?url=https://lafen.gitee.io/2019/11/20/vue-项目记录/vue-项目记录/&title=《vue-项目记录》 — lafen&source=lafen's personal blog" data-title=" QQ">
          <i class="icon icon-qq"></i>
        </a>
      </li>
      <li>
        <a class="facebook share-sns" target="_blank" href="https://www.facebook.com/sharer/sharer.php?u=https://lafen.gitee.io/2019/11/20/vue-项目记录/vue-项目记录/" data-title=" Facebook">
          <i class="icon icon-facebook"></i>
        </a>
      </li>
      <li>
        <a class="twitter share-sns" target="_blank" href="https://twitter.com/intent/tweet?text=《vue-项目记录》 — lafen&url=https://lafen.gitee.io/2019/11/20/vue-项目记录/vue-项目记录/&via=https://lafen.gitee.io" data-title=" Twitter">
          <i class="icon icon-twitter"></i>
        </a>
      </li>
      <li>
        <a class="google share-sns" target="_blank" href="https://plus.google.com/share?url=https://lafen.gitee.io/2019/11/20/vue-项目记录/vue-项目记录/" data-title=" Google+">
          <i class="icon icon-google-plus"></i>
        </a>
      </li>
    </ul>
 </div>



    <a href="javascript:;" id="shareFab" class="page-share-fab waves-effect waves-circle">
        <i class="icon icon-share-alt icon-lg"></i>
    </a>
</div>



        </div>
    </div>

    
<nav class="post-nav flex-row flex-justify-between">
  
    <div class="waves-block waves-effect prev">
      <a href="/2019/11/23/js-深入-new模拟实现/js-深入-new模拟实现/" id="post-prev" class="post-nav-link">
        <div class="tips"><i class="icon icon-angle-left icon-lg icon-pr"></i> Prev</div>
        <h4 class="title">js-深入-new模拟实现</h4>
      </a>
    </div>
  

  
    <div class="waves-block waves-effect next">
      <a href="/2019/11/17/vue-源码笔记/vue-源码笔记/" id="post-next" class="post-nav-link">
        <div class="tips">Next <i class="icon icon-angle-right icon-lg icon-pl"></i></div>
        <h4 class="title">vue-源码笔记</h4>
      </a>
    </div>
  
</nav>



    




















</article>

<div id="reward" class="page-modal reward-lay">
    <a class="close" href="javascript:;"><i class="icon icon-close"></i></a>
    <h3 class="reward-title">
        <i class="icon icon-quote-left"></i>
        打笔巨款？~
        <i class="icon icon-quote-right"></i>
    </h3>
    <div class="reward-content">
        
        <div class="reward-code">
            <img id="rewardCode" src="/img/wechat.jpg" alt="打赏二维码">
        </div>
        
        <label class="reward-toggle">
            <input id="rewardToggle" type="checkbox" class="reward-toggle-check" data-wechat="/img/wechat.jpg" data-alipay="/img/alipay.jpg">
            <div class="reward-toggle-ctrol">
                <span class="reward-toggle-item wechat">微信</span>
                <span class="reward-toggle-label"></span>
                <span class="reward-toggle-item alipay">支付宝</span>
            </div>
        </label>
        
    </div>
</div>



</div>

        <footer class="footer">
    <div class="top">
        
<p>
    <span id="busuanzi_container_site_uv" style="display:none">
        站点总访客数：<span id="busuanzi_value_site_uv"></span>
    </span>
    <span id="busuanzi_container_site_pv" style="display:none">
        站点总访问量：<span id="busuanzi_value_site_pv"></span>
    </span>
</p>


        <p>
            
                <span><a href="/atom.xml" target="_blank" class="rss" title="rss"><i class="icon icon-lg icon-rss"></i></a></span>
            
            <span>博客内容遵循 <a rel="license" href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh">知识共享 署名 - 非商业性 - 相同方式共享 4.0 国际协议</a></span>
        </p>
    </div>
    <div class="bottom">
        <p><span>lafen &copy; 2019 - 2020</span>
            <span>
                
                Power by <a href="http://hexo.io/" target="_blank">Hexo</a> Theme <a href="https://github.com/yscoder/hexo-theme-indigo" target="_blank">indigo</a>
            </span>
        </p>
    </div>
</footer>

    </main>
    <div class="mask" id="mask"></div>
<a href="javascript:;" id="gotop" class="waves-effect waves-circle waves-light"><span class="icon icon-lg icon-chevron-up"></span></a>



<div class="global-share" id="globalShare">
    <ul class="reset share-icons">
      <li>
        <a class="weibo share-sns" target="_blank" href="http://service.weibo.com/share/share.php?url=https://lafen.gitee.io/2019/11/20/vue-项目记录/vue-项目记录/&title=《vue-项目记录》 — lafen&pic=https://lafen.gitee.io/img/avatar.jpg" data-title="微博">
          <i class="icon icon-weibo"></i>
        </a>
      </li>
      <li>
        <a class="weixin share-sns wxFab" href="javascript:;" data-title="微信">
          <i class="icon icon-weixin"></i>
        </a>
      </li>
      <li>
        <a class="qq share-sns" target="_blank" href="http://connect.qq.com/widget/shareqq/index.html?url=https://lafen.gitee.io/2019/11/20/vue-项目记录/vue-项目记录/&title=《vue-项目记录》 — lafen&source=lafen's personal blog" data-title=" QQ">
          <i class="icon icon-qq"></i>
        </a>
      </li>
      <li>
        <a class="facebook share-sns" target="_blank" href="https://www.facebook.com/sharer/sharer.php?u=https://lafen.gitee.io/2019/11/20/vue-项目记录/vue-项目记录/" data-title=" Facebook">
          <i class="icon icon-facebook"></i>
        </a>
      </li>
      <li>
        <a class="twitter share-sns" target="_blank" href="https://twitter.com/intent/tweet?text=《vue-项目记录》 — lafen&url=https://lafen.gitee.io/2019/11/20/vue-项目记录/vue-项目记录/&via=https://lafen.gitee.io" data-title=" Twitter">
          <i class="icon icon-twitter"></i>
        </a>
      </li>
      <li>
        <a class="google share-sns" target="_blank" href="https://plus.google.com/share?url=https://lafen.gitee.io/2019/11/20/vue-项目记录/vue-项目记录/" data-title=" Google+">
          <i class="icon icon-google-plus"></i>
        </a>
      </li>
    </ul>
 </div>


<div class="page-modal wx-share" id="wxShare">
    <a class="close" href="javascript:;"><i class="icon icon-close"></i></a>
    <p>扫一扫，分享到微信</p>
    <img src="" alt="微信分享二维码">
</div>




    <script src="//cdn.bootcss.com/node-waves/0.7.4/waves.min.js"></script>
<script>
var BLOG = { ROOT: '/', SHARE: true, REWARD: true };


</script>

<script src="//unpkg.com/hexo-theme-material-indigo@latest/js/main.min.js"></script>


<div class="search-panel" id="search-panel">
    <ul class="search-result" id="search-result"></ul>
</div>
<template id="search-tpl">
<li class="item">
    <a href="{path}" class="waves-block waves-effect">
        <div class="title ellipsis" title="{title}">{title}</div>
        <div class="flex-row flex-middle">
            <div class="tags ellipsis">
                {tags}
            </div>
            <time class="flex-col time">{date}</time>
        </div>
    </a>
</li>
</template>

<script src="//unpkg.com/hexo-theme-material-indigo@latest/js/search.min.js" async></script>






<script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>



<script>
(function() {
    var OriginTitile = document.title, titleTime;
    document.addEventListener('visibilitychange', function() {
        if (document.hidden) {
            document.title = '死鬼去哪里了！';
            clearTimeout(titleTime);
        } else {
            document.title = '(つェ⊂)咦!又好了!';
            titleTime = setTimeout(function() {
                document.title = OriginTitile;
            },2000);
        }
    });
})();
</script>



<script src="/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"pluginRootPath":"live2dw/","pluginJsPath":"lib/","pluginModelPath":"assets/","tagMode":false,"debug":false,"model":{"scale":1,"jsonPath":"/live2dw/assets/shizuku.model.json"},"display":{"positon":"right","width":150,"height":300},"mobile":{"show":true,"scale":0.8},"react":{"opacity":0.8,"opacityDefault":0.8,"opacityOnHover":0.6},"log":false});</script></body>
</html>
